/*
 * Copyright (C) 2004-2006 nickyb@users.sourceforge.net
 * 
 * This file is part of FreeQueryBuilder (http://querybuilder.sourceforge.net)
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package net.sourceforge.querybuilder;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Font;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import java.text.NumberFormat;

import java.util.Arrays;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class QueryPreview extends JFrame implements Runnable
{
	Thread me		= null;
	
	ResultSet rs	= null;
	Statement stmt	= null;
	Connection conn	= null;

	JLabel status;
	JTextArea output;
	
	public QueryPreview(Connection connection, String sql)
	{
		super("Preview - " + MainWindow.TITLE);
		conn = connection;
		
		status = new JLabel();
		status.setBorder(new CompoundBorder(LineBorder.createGrayLineBorder(), new EmptyBorder(3,4,3,4)));
		
		getContentPane().add(new JScrollPane(output = new JTextArea())	, BorderLayout.CENTER);
		getContentPane().add(status										, BorderLayout.SOUTH);
		
		setSize(640,480);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		
		WindowListener wl = new WindowAdapter()
		{
			public void windowClosing(WindowEvent we)
			{
				QueryPreview.this.me = null;
				QueryPreview.this.dispose();
			}
		};
		addWindowListener(wl);
		
		output.setFont(new Font("monospaced",Font.PLAIN,13));
		output.setEditable(false);
		output.setTabSize(4);
		output.setText(sql);
		
		startThread();
	}
	
	void startThread()
	{
		me = new Thread(this);
		me.start();
	}
	
	public void run()
	{
		output.setCursor(new Cursor(Cursor.WAIT_CURSOR));
		status.setText("waiting response...");
		
		String request = output.getText();
		StringBuffer responseBuffer = new StringBuffer();
		
		try
		{
			stmt = conn.createStatement();
			rs = stmt.executeQuery(request);
			
			print(responseBuffer);
			
			rs.close();
			stmt.close();
		}
		catch(SQLException sqle)
		{
			responseBuffer.append(sqle.toString()+"\n");
			status.setText("SQLException!");
		}
		finally
		{
			output.setText(responseBuffer.toString());
			output.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
			
			conn = null;
		}
	}
	
	int maxSize = 50;

	private void print(StringBuffer stream)
		throws SQLException
	{
		if(rs==null) return;
		ResultSetMetaData rsmd = rs.getMetaData();
		
		long started = System.currentTimeMillis();
		status.setText("reading...");
		
		StringBuffer header = new StringBuffer("| ");
		StringBuffer divider = new StringBuffer("+-");
		
		int columnDisplaySize[] = new int[rsmd.getColumnCount()];
		for(int i=1; i<=rsmd.getColumnCount(); i++)
		{
			header.append(rsmd.getColumnLabel(i));
			
			char[] filler = new char[rsmd.getColumnLabel(i).length()];
			Arrays.fill(filler, '-');
			divider.append(filler);
			
			columnDisplaySize[i-1] = rsmd.getColumnDisplaySize(i);
			int diff = columnDisplaySize[i-1] - rsmd.getColumnLabel(i).length();
			
			if(diff > 0)
			{
				if(diff > maxSize)
				{
					diff = maxSize - rsmd.getColumnLabel(i).length();
					columnDisplaySize[i-1] = maxSize;
				}
				
				filler = new char[diff];
				Arrays.fill(filler, ' ');
				header.append(filler);

				Arrays.fill(filler, '-');
				divider.append(filler);
			}
			else
			{
				columnDisplaySize[i-1] = rsmd.getColumnLabel(i).length();
			}

			header.append(" | ");
			divider.append("-+-");
		}
		
		divider.deleteCharAt(divider.length()-1);
		header.deleteCharAt(header.length()-1);
		
		stream.append(divider.toString() + "\n");
		stream.append(header.toString() + "\n");
		stream.append(divider.toString() + "\n");
		
		int bytes = 0;
		int rowcount = 0;
		while(rs.next() && me!=null)
		{
			status.setText("reading record " + (++rowcount) + " , bytes " + bytes);
			
			StringBuffer row = new StringBuffer("| ");
				
			for(int i=1; i<=rsmd.getColumnCount(); i++)
			{
				String value = rs.getString(i);
				if(value==null) value = new String();
				
				bytes += value.length();
				
				int diff = columnDisplaySize[i-1] - value.length();
				if(diff > 0)
				{
					char[] filler = new char[diff];
					Arrays.fill(filler, ' ');
					row.append(value + new String(filler));
				}
				else if(diff < 0)
				{
					value = value.substring(0, columnDisplaySize[i-1]-3);
					row.append(value + "...");
				}
				else
					row.append(value);
				
				row.append(" | ");
			}
				
			stream.append(row.toString()+"\n");
		}
		
		long ended = System.currentTimeMillis();
		
		status.setText("records: " + NumberFormat.getInstance().format(rowcount) + " [ time: " + NumberFormat.getInstance().format((ended - started)) + " bytes: " + NumberFormat.getInstance().format(bytes) + " ]");
		if(rowcount>0) stream.append(divider.toString() + "\n");
	}
}